package element.synt;

import element.base.Synt;
import element.base.TreeNode;
import element.base.Word;
import element.base.Wordtype;
import intermediate_representation.FuncDefRP;
import intermediate_representation.ParaRP;
import symbal.Symbal;
import symbal.Vtype;
import table.InterCodeTable;

import java.util.ArrayList;

//FuncDef → FuncType Ident '(' [FuncFParams] ')' Block
//FuncFParams → FuncFParam { ',' FuncFParam }
//FuncFParam → BType Ident ['[' ']' { '[' ConstExp ']' }]
public class FuncDef extends Synt {
    @Override
    public void tointerRP() {
        InterCodeTable.endGlobal();
        ArrayList<TreeNode> nodes = this.getNodes();
        Word type = this.findFirst();
        String name = ((Word) nodes.get(1)).getContent();
        Vtype vtype;
        if (type.isWord(Wordtype.VOIDTK)) {
            vtype = Vtype.VOID;
        } else {
            vtype = Vtype.INT;
        }
        Symbal funcsymbal = new Symbal(name, Vtype.FUNC, vtype);
        String mipsname = "func" + InterCodeTable.funcnum;
        funcsymbal.setMipsName(mipsname);
        InterCodeTable.funcnum++;
        FuncDefRP funcDefRP = new FuncDefRP(mipsname, vtype);

        if (nodes.get(3) instanceof FuncFParams) {
            FuncFParams funcFParams = (FuncFParams) nodes.get(3);
            ArrayList<TreeNode> subnodes = funcFParams.getNodes();
            for (TreeNode node: subnodes) {
                if (node instanceof FuncFParam) {
                    ArrayList<TreeNode> subsubnodes = ((FuncFParam) node).getNodes();
                    if (subsubnodes.size() == 2) {
                        String paraname = ((Word) subsubnodes.get(1)).getContent();
                        Symbal symbal = new Symbal(paraname, Vtype.INT);
                        String pmipsname = "para" + InterCodeTable.paranum;
                        symbal.setMipsName(pmipsname);
                        InterCodeTable.paranum++;
                        InterCodeTable.paraTable.add(symbal);
                        funcsymbal.addAttr(Vtype.INT);
                        ParaRP paraRP = new ParaRP(pmipsname, 0);
                        funcDefRP.addPara(paraRP);
                    } else if (subsubnodes.size() == 4) {
                        String paraname = ((Word) subsubnodes.get(1)).getContent();
                        Symbal symbal = new Symbal(paraname, Vtype.INT1);
                        String pmipsname = "para" + InterCodeTable.paranum;
                        symbal.setMipsName(pmipsname);
                        InterCodeTable.paranum++;
                        InterCodeTable.paraTable.add(symbal);
                        funcsymbal.addAttr(Vtype.INT1);
                        ParaRP paraRP = new ParaRP(pmipsname, 1);
                        funcDefRP.addPara(paraRP);
                    } else {
                        String paraname = ((Word) subsubnodes.get(1)).getContent();
                        Symbal symbal = new Symbal(paraname, Vtype.INT2);
                        ConstExp len2exp = (ConstExp) subsubnodes.get(5);
                        int len2 = len2exp.calcu();
                        symbal.setLen2(len2);
                        String pmipsname = "para" + InterCodeTable.paranum;
                        symbal.setMipsName(pmipsname);
                        InterCodeTable.paranum++;
                        InterCodeTable.paraTable.add(symbal);
                        funcsymbal.addAttr(Vtype.INT2);
                        ParaRP paraRP = new ParaRP(pmipsname, 2, len2);
                        funcDefRP.addPara(paraRP);
                    }
                }
            }
        }
        InterCodeTable.symbalTable.addSymbal(funcsymbal);
        InterCodeTable.addCode(funcDefRP);
        Block block = (Block) nodes.get(nodes.size() - 1);
        block.tointerRP();
    }
}
